package pre;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import io.DataSet;

public class ForestFiresHistogram extends Histogram {

	private static final double X_SIGMA = 3.0;
	private static final double Y_SIGMA = 2.0;
	private static final double MONTH_SIN_SIGMA = 0.1;
	private static final double MONTH_COS_SIGMA = 0.1;
	private static final double DAY_SIN_SIGMA = 0.1;
	private static final double DAY_COS_SIGMA = 0.1;
	private static final double FFMC_SIGMA = 5.5;
	private static final double DMC_SIGMA = 100.0;
	private static final double DC_SIGMA = 110.0;
	private static final double ISI_SIGMA = 6.0;
	private static final double TEMP_SIGMA = 10.0;
	private static final double RH_SIGMA = 20.0;
	private static final double WIND_SIGMA = 2.0;
	private static final double RAIN_SIGMA = 1.0; //Almost all zero.
	
	private static final int NUMBER_INVERVALS = 1001; //Must be an odd number.
	
	private File file;
	private FileWriter writer;
	
	public ForestFiresHistogram() {
		super();
		dataSet = new DataSet("data/forestfires.csv");
	}
	
	@Override
	public void generate() {
		int col = 11; //Attribute to generate the histogram data.
		double max_distance = Double.MIN_VALUE;
		List<Double> distances = new ArrayList<Double>((int)Math.pow(dataSet.getRowSize(), 2));
		
		for(int i=0; i<dataSet.getRowSize(); i++) {
			for(int j=0; j<dataSet.getRowSize(); j++) {
				if(i != j) {
					double x1 = Double.parseDouble(dataSet.getValue(i, col));
					double x2 = Double.parseDouble(dataSet.getValue(j, col));
					
					/*
					//Attribute 2 must be parsed twice, for sin and cos.
					double x1 = getMonthSin(getNumericMonth(dataSet.getValue(i, 2)));
					double x2 = getMonthSin(getNumericMonth(dataSet.getValue(j, 2)));
					
					double x1 = getMonthCos(getNumericMonth(dataSet.getValue(i, 2)));
					double x2 = getMonthCos(getNumericMonth(dataSet.getValue(j, 2)));
					*/
					
					/*
					//Attribute 3 must be parsed twice, for sin and cos.
					double x1 = getDaySin(getNumericDay(dataSet.getValue(i, 3)));
					double x2 = getDaySin(getNumericDay(dataSet.getValue(j, 3)));
					
					double x1 = getDayCos(getNumericDay(dataSet.getValue(i, 3)));
					double x2 = getDayCos(getNumericDay(dataSet.getValue(j, 3)));
					*/
					
					/*
					//Attribute 12 must go through the log function.
					double x1 = Math.log(Double.parseDouble(dataSet.getValue(i, col)) + 1.0);
					double x2 = Math.log(Double.parseDouble(dataSet.getValue(j, col)) + 1.0);
					*/
					
					
					double distance = x1 - x2;
					distances.add(distance);
					if(distance > max_distance)
						max_distance = distance;
				}
			}
		}
		
		int[] count = new int[NUMBER_INVERVALS];
		
		for(int i=0; i<NUMBER_INVERVALS-1; i++)
			count[i] = 0;
		
		for(Double x : distances) {
			count[(int)Math.floor((x/max_distance)*(NUMBER_INVERVALS/2))+(NUMBER_INVERVALS/2)] += 1;
		}
		
		file = new File("histograms\\attribute" + String.valueOf(col) + ".dat");
		//file = new File("histograms\\attribute" + String.valueOf(col) + "s.dat");
		//file = new File("histograms\\attribute" + String.valueOf(col) + "c.dat");
		writer = null;
		try {
			writer = new FileWriter(file);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		String toWrite = new String();
		for(int i=0; i<NUMBER_INVERVALS-2; i++) {
			toWrite = toWrite.concat( ( (double) (i -(NUMBER_INVERVALS/2) ) / (NUMBER_INVERVALS/2) )*max_distance + "\t" + String.valueOf(count[i]) + "\n");
		}
		toWrite = toWrite.concat( ( (double) (NUMBER_INVERVALS-1 -(NUMBER_INVERVALS/2) ) / (NUMBER_INVERVALS/2) )*max_distance + "\t" + String.valueOf(count[NUMBER_INVERVALS-1]) + "\n");
		try {
			writer.write(toWrite);
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private int getNumericMonth(String month) {
		int numeric;
		if(month.equals("jan")) {
			numeric = 0;
		}
		else if(month.equals("feb")) {
			numeric = 1;
		}
		else if(month.equals("mar")) {
			numeric = 2;
		}
		else if(month.equals("apr")) {
			numeric = 3;
		}
		else if(month.equals("may")) {
			numeric = 4;
		}
		else if(month.equals("jun")) {
			numeric = 5;
		}
		else if(month.equals("jul")) {
			numeric = 6;
		}
		else if(month.equals("aug")) {
			numeric = 7;
		}
		else if(month.equals("sep")) {
			numeric = 8;
		}
		else if(month.equals("oct")) {
			numeric = 9;
		}
		else if(month.equals("nov")) {
			numeric = 10;
		}
		else if(month.equals("dec")) {
			numeric = 11;
		}
		else
			numeric = -1;
		
		return numeric;
	}
	
	public int getNumericDay(String day) {
		int numeric;
		if(day.equals("mon")) {
			numeric = 0;
		}
		else if(day.equals("tue")) {
			numeric = 1;
		}
		else if(day.equals("wed")) {
			numeric = 2;
		}
		else if(day.equals("thu")) {
			numeric = 3;
		}
		else if(day.equals("fri")) {
			numeric = 4;
		}
		else if(day.equals("sat")) {
			numeric = 5;
		}
		else if(day.equals("sun")) {
			numeric = 6;
		}
		else
			numeric = -1;
		
		return numeric;
	}
	
	public double getMonthSin(int month) {
		return Math.sin(2.0*Math.PI*month/12.0);
	}
	
	public double getMonthCos(int month) {
		return Math.cos(2.0*Math.PI*month/12.0);
	}
	
	public double getDaySin(int day) {
		return Math.sin(2.0*Math.PI*day/7.0);
	}
	
	public double getDayCos(int day) {
		return Math.cos(2.0*Math.PI*day/7.0);
	}
}
